package cn.lyjuan.payment.third.base.pay.chl.impl.weixin.util;

import cn.lyjuan.base.util.DigestUtils;
import cn.lyjuan.base.util.HttpUtils;
import cn.lyjuan.base.util.XmlUtils;
import cn.lyjuan.payment.third.base.pay.chl.impl.weixin.bean.WxChlCnf;
import cn.lyjuan.payment.third.base.pay.chl.impl.weixin.bean.WxQueryReq;
import cn.lyjuan.payment.third.base.pay.cst.PayConst;
import cn.lyjuan.payment.third.base.pay.vo.req.QueryReq;

import java.util.HashMap;
import java.util.Map;

public class WxpayQuery
{
    /**
     * 订单状态查询地址
     */
    private static final String QUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery";

    /**
     * 创建微信手机网页支付结果查询请求参数
     *
     * @param order 交易、订单信息
     * @return 查询交易状态的XML信息
     */
    public static String createTradeQuery(QueryReq<WxQueryReq> order, WxChlCnf cnf)
    {
        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", cnf.getAppId());
        params.put("mch_id", cnf.getMchId());
        params.put("transaction_id", order.getTranNo());
        params.put("out_trade_no", order.getLocalNo());
        params.put("nonce_str", "nonce_str");

        // 32位 MD5 签名字符串
        String signStr = WxUtils.sortParamForSign(params);

        // 根据密钥进行 MD5 签名
        String sign = DigestUtils.md5LowerCase(signStr + "&key=" + cnf.getKey(), PayConst.CHARSET);
        sign = sign.toUpperCase();
        params.put("sign", sign);

        String xml = WxUtils.sortParamXml(params);

        return xml;
    }


    /**
     * 请求查询微信手机网页支付订单状态
     *
     * @param xml 请求XML
     * @return
     */
    public static Map<String, String> sendTradeQuery(String xml)
    {
        try
        {
            String tradeQueryResp = HttpUtils.sendPost(QUERY_URL, xml, false, PayConst.CHARSET, null);

            // 解析查询结果
            return parseTradeQueryMsg(tradeQueryResp);

        } catch (Exception e)
        {
            // todo 返回错误参数
            Map<String, String> result = new HashMap<>(4);
            result.put("return_code", WxpaySubmit.FAIL);
            result.put("return_msg", e.getMessage());
            result.put("result_code", WxpaySubmit.FAIL);
            result.put("err_code_des", e.getMessage());
            return result;
        }
    }

    /**
     * 解析微信手机网页支付查询订单状态结果
     *
     * @param tradeQueryResp
     * @return
     */
    private static Map<String, String> parseTradeQueryMsg(String tradeQueryResp)
    {
        Map<String, String> params = new HashMap<String, String>();

        params.put("return_code", XmlUtils.getMember(tradeQueryResp, "return_code"));
        params.put("return_msg", XmlUtils.getMember(tradeQueryResp, "return_msg"));
        params.put("appid", XmlUtils.getMember(tradeQueryResp, "appid"));
        params.put("mch_id", XmlUtils.getMember(tradeQueryResp, "mch_id"));
        params.put("nonce_str", XmlUtils.getMember(tradeQueryResp, "nonce_str"));
        params.put("sign", XmlUtils.getMember(tradeQueryResp, "sign"));
        params.put("result_code", XmlUtils.getMember(tradeQueryResp, "result_code"));
        params.put("err_code", XmlUtils.getMember(tradeQueryResp, "err_code"));
        params.put("err_code_des", XmlUtils.getMember(tradeQueryResp, "err_code_des"));
        params.put("trade_state", XmlUtils.getMember(tradeQueryResp, "trade_state"));
        params.put("device_info", XmlUtils.getMember(tradeQueryResp, "device_info"));
        params.put("openid", XmlUtils.getMember(tradeQueryResp, "openid"));
        params.put("is_subscribe", XmlUtils.getMember(tradeQueryResp, "is_subscribe"));
        params.put("trade_type", XmlUtils.getMember(tradeQueryResp, "trade_type"));
        params.put("bank_type", XmlUtils.getMember(tradeQueryResp, "bank_type"));
        params.put("total_fee", XmlUtils.getMember(tradeQueryResp, "total_fee"));
        params.put("coupon_fee", XmlUtils.getMember(tradeQueryResp, "coupon_fee"));
        params.put("fee_type", XmlUtils.getMember(tradeQueryResp, "fee_type"));
        params.put("transaction_id", XmlUtils.getMember(tradeQueryResp, "transaction_id"));
        params.put("out_trade_no", XmlUtils.getMember(tradeQueryResp, "out_trade_no"));
        params.put("attach", XmlUtils.getMember(tradeQueryResp, "attach"));
        params.put("time_end", XmlUtils.getMember(tradeQueryResp, "time_end"));

        return params;
    }

}
